home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / ui / document.c < prev    next >
C/C++ Source or Header  |  1995-01-09  |  19KB  |  777 lines

  1. /* 
  2.   WIDE AREA INFORMATION SERVER SOFTWARE:
  3.    No guarantees or restrictions.  See the readme file for the full standard
  4.    disclaimer.
  5.  
  6.    This is part of the shell user-interface tools for the WAIS software.
  7.    Do with it as you please.
  8.  
  9.    jonathan@Think.COM
  10. */
  11.  
  12. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  13.  
  14. /*
  15.  * $Log: document.c,v $
  16.  * Revision 1.3  1995/01/10  16:51:38  pfeifer
  17.  * Little fix for multiple submissions of the same query, which breaks xwasq.
  18.  * Not the last!
  19.  *
  20.  * Revision 1.2  1994/08/05  07:29:53  pfeifer
  21.  * Release beta 04
  22.  *
  23.  * Revision 1.1  93/06/23  20:02:04  warnock
  24.  * Initial revision
  25.  * 
  26.  * Revision 1.1  1993/02/16  15:09:27  freewais
  27.  * Initial revision
  28.  *
  29.  * Revision 1.10  92/05/07  14:50:27  jonathan
  30.  * Fixed listing for sections starting at 0.
  31.  * 
  32.  * Revision 1.9  92/04/02  14:23:36  jonathan
  33.  * fleshed out copy_cretdoc.
  34.  * 
  35.  * Revision 1.8  92/04/01  17:16:20  jonathan
  36.  * Added some copying functions.
  37.  * 
  38.  * Revision 1.7  92/03/17  14:36:40  jonathan
  39.  * Cleaned up for use with X interface as well.
  40.  * 
  41.  * Revision 1.6  92/03/08  09:13:13  jonathan
  42.  * strip lf from headlines.
  43.  * 
  44.  */
  45.  
  46. #ifndef lint
  47. static char *RCSid = "$Header: /usr/local/ls6/src+data/src/freeWAIS-sf/ui/RCS/document.c,v 1.3 1995/01/10 16:51:38 pfeifer Exp $";
  48. #endif
  49.  
  50. #include "wais.h"
  51. #include "util.h"
  52. #include "globals.h"
  53. #include "document.h"
  54.  
  55.  
  56. static void** copyList(list)
  57. void **list;
  58. {
  59.   void **result = NULL;
  60.   void **l1, **l2;
  61.   long i;
  62.  
  63.   if(list != NULL) {
  64.     for(l1 = list, i = 0; *l1 != NULL; i++, l1++);
  65.       if((result = (void**)s_malloc((1+i)*sizeof(void*))) != NULL) {
  66.       for(l1 = list, l2 = result; *l1 != NULL; l1++, l2++) {
  67.     *l2 = s_strdup(*l1);
  68.       }
  69.       result[i] = NULL;
  70.     }
  71.   }
  72.   return result;
  73. }
  74.       
  75. static void freeList(list)
  76. void **list;
  77. {
  78.   void** l = list;
  79.   while(*l != NULL) {
  80.     s_free(*l);
  81.     l++;
  82.   }
  83.   s_free(list);
  84. }
  85.  
  86. static void strip_lf(line)
  87. char *line;
  88. {
  89.   long i;
  90.  
  91.   if (line!=NULL) {
  92.     do {
  93.       if (*line=='\r' || *line=='\n') *line='_';
  94.     } while(*line++);
  95.   }
  96. }
  97.     
  98. static void
  99. setdate(date, source)
  100. char *date, *source;
  101. {
  102.   date[8] = 0;
  103.   date[2] = date[5] = '/';
  104.   date[0] = source[2];
  105.   date[1] = source[3];
  106.   date[3] = source[4];
  107.   date[4] = source[5];
  108.   date[6] = source[0];
  109.   date[7] = source[1];
  110. }
  111.  
  112. void
  113. freeItemList(list)
  114. char **list;
  115. {
  116.   char **temp;
  117.  
  118.   temp = list;
  119.  
  120.   while(*temp != NULL) {
  121.     s_free(*temp);
  122.     temp++;
  123.   }
  124.  
  125.   s_free (list);
  126. }
  127.  
  128. char **
  129. buildDocumentItemList(doclist, scorep)
  130. DocList doclist;
  131. Boolean scorep;
  132. {
  133.   char **result, date[9];
  134.   int num, i;
  135.   DocList doc;
  136.  
  137.   /* find the length of the doclist in the question */
  138.  
  139.   for(num = 0, doc = doclist;
  140.       doc != NULL && doc->thisDoc != NULL;
  141.       num++, doc = doc->nextDoc);
  142.  
  143.   result = (char**) s_malloc((1+num)*sizeof(char*));
  144.   result[num] = NULL;
  145.   if(num > 0)
  146.     for(i = 0, doc = doclist; i<num; i++, doc = doc->nextDoc) {
  147.       if(doc->thisDoc != NULL) {
  148.     if(scorep == TRUE) {
  149.       result[i] = s_malloc(strlen(doc->thisDoc->doc->headline)+26);
  150.       if ((doc->thisDoc->doc->date == NULL) ||
  151.           (strcmp(doc->thisDoc->doc->date, "0") == 0)) {
  152.         if (doc->thisDoc->doc->numChars > 1024)
  153.           sprintf(result[i], "%5d %4.1fK %s", 
  154.               doc->thisDoc->rawScore,
  155.               ((float)doc->thisDoc->doc->numChars/1024.0),
  156.               doc->thisDoc->doc->headline);
  157.         else
  158.           sprintf(result[i], "%5d %5d %s", 
  159.               doc->thisDoc->rawScore,
  160.               doc->thisDoc->doc->numChars,
  161.               doc->thisDoc->doc->headline);
  162.       }
  163.       else {
  164.         setdate(date, doc->thisDoc->doc->date);
  165.         if (doc->thisDoc->doc->numChars > 1024)
  166.           sprintf(result[i], "%5d %4.1fK (%s) %s",
  167.               doc->thisDoc->rawScore, 
  168.               ((float)doc->thisDoc->doc->numChars/1024.0),
  169.               date,
  170.               doc->thisDoc->doc->headline);
  171.         else
  172.           sprintf(result[i], "%5d %4d (%s) %s",
  173.               doc->thisDoc->rawScore, 
  174.               doc->thisDoc->doc->numChars,
  175.               date,
  176.               doc->thisDoc->doc->headline);
  177.         
  178.       }
  179.     }
  180.     else {
  181.       result[i] = s_malloc(strlen(doc->thisDoc->doc->headline)+30);
  182.       if(doc->thisDoc->end > 0) {
  183.         if ((doc->thisDoc->doc->date != NULL) &&
  184.         (strcmp(doc->thisDoc->doc->date, "0") != 0)) {
  185.           setdate(date, doc->thisDoc->doc->date);
  186.           sprintf(result[i], "[%d,%d] (%s) %s", 
  187.               doc->thisDoc->start, doc->thisDoc->end, date,
  188.               doc->thisDoc->doc->headline);
  189.         }
  190.         else {
  191.           sprintf(result[i], "[%d,%d] %s", 
  192.               doc->thisDoc->start, doc->thisDoc->end,
  193.               doc->thisDoc->doc->headline);
  194.         }
  195.       }
  196.       else
  197.         if ((doc->thisDoc->doc->date != NULL) &&
  198.         (strcmp(doc->thisDoc->doc->date, "0") != 0)) {
  199.           setdate(date, doc->thisDoc->doc->date);
  200.           sprintf(result[i], "(%s) %s",
  201.               date, doc->thisDoc->doc->headline);
  202.         }
  203.         else {
  204.           sprintf(result[i], "%s", doc->thisDoc->doc->headline);
  205.         }
  206.     }
  207.       }
  208.       if(result[i] != NULL) result[i] = trim_junk(result[i]);
  209.     }
  210.   return(result);
  211. }
  212.  
  213. DocList ReadListOfDocuments(file)
  214. FILE *file;
  215. {
  216.   short check_result;
  217.   DocumentID documentid = NULL;
  218.   DocList result, this, last;
  219.           
  220.   /* initialize */
  221.   this = last = result = NULL;
  222.  
  223.   if(ReadStartOfList(file) == FALSE)
  224.     return(NULL);
  225.  
  226.   while(TRUE) {
  227.     documentid = (DocumentID)s_malloc(sizeof(_DocumentID));
  228.     documentid->start = -1;
  229.     documentid->end = -1;
  230.     check_result = ReadDocument(documentid, file);
  231.     if(check_result == END_OF_STRUCT_OR_LIST) {
  232.       s_free(documentid);
  233.       return(result);
  234.     }
  235.     else if(check_result == FALSE)
  236.       return(result);
  237.  
  238.     else if(check_result == TRUE) {
  239.       if(result == NULL)
  240.     result = this = (DocList)s_malloc(sizeof(_DocList));
  241.       else
  242.     this = (DocList)s_malloc(sizeof(_DocList));
  243.       this->thisDoc = documentid;
  244.       if(last != NULL)
  245.     last->nextDoc = this;
  246.       last = this;
  247.     }
  248.   }
  249. }
  250.  
  251. short
  252. ReadFragment(file, dest)
  253. FILE *file;
  254. long *dest;
  255. {
  256.   char temp_string[MAX_SYMBOL_SIZE];
  257.   short check_result;
  258.  
  259.   /* initialize */
  260.   check_result = CheckStartOfStruct("fragment", file);
  261.  
  262.   if(FALSE == check_result){ 
  263.     return(false);
  264.   }
  265.   if(END_OF_STRUCT_OR_LIST == check_result)
  266.     {
  267.       return(FALSE);
  268.     }
  269.     
  270.   /* read the slots: */
  271.   while(check_result != END_OF_STRUCT_OR_LIST){
  272.     short check_result = ReadSymbol(temp_string, file, MAX_SYMBOL_SIZE);
  273.     if(END_OF_STRUCT_OR_LIST == check_result) {
  274.       return(true);
  275.     }
  276.     if(0 == strcmp(temp_string, ":byte-pos")){
  277.       if(FALSE == ReadLong(file, dest)){
  278.     return(false);
  279.       }
  280.     }
  281.     else if(0 == strcmp(temp_string, ":line-pos")){
  282.       if(FALSE == ReadLong(file, dest)){
  283.     return(false);
  284.       }
  285.     }
  286.     else if(0 == strcmp(temp_string, ":para-id")){
  287.       if(FALSE == ReadLong(file, dest)){
  288.     return(false);
  289.       }
  290.     }
  291.     else            /* we don't know what this is */
  292.       SkipObject(file);
  293.   }
  294.   return(true);
  295. }
  296.  
  297. /* Read a document from a file.  If it is the end of a list instead of
  298.  * at a document, then return END_OF_STRUCT_OR_LIST, 
  299.  * if it hits an error on loading, return FALSE,
  300.  * otherwise return TRUE.
  301.  */
  302. short
  303. ReadDoc(file, doc)
  304. FILE *file;
  305. CRetDocument doc;
  306. {
  307.   char temp_string[MAX_SYMBOL_SIZE];
  308.   short check_result;
  309.   long lines, chars, best;
  310.   long i, numtypes = 0;
  311.   char *types[100];
  312.   DocID* docid = NULL;
  313.   SourceID aSid;
  314.   char headline[MAX_SYMBOL_SIZE];
  315.   char dateStr[MAX_SYMBOL_SIZE];
  316.           
  317.   /* initialize */
  318.   check_result = CheckStartOfStruct("document", file);
  319.   headline[0] = '\0';
  320.   dateStr[0] = '\0';
  321.  
  322.   if(FALSE == check_result){ 
  323.     return(false);
  324.   }
  325.   if(END_OF_STRUCT_OR_LIST == check_result)
  326.     {
  327.       return(FALSE);
  328.     }
  329.     
  330.   /* read the slots: */
  331.   while(check_result != END_OF_STRUCT_OR_LIST){
  332.     short check_result = ReadSymbol(temp_string, file, MAX_SYMBOL_SIZE);
  333.     if(END_OF_STRUCT_OR_LIST == check_result) {
  334.       if(*headline != 0)
  335.     doc->headline = s_strdup(headline);
  336.       doc->type = (char**)s_malloc((numtypes+1)*sizeof(char*));
  337.       for(i = 0; i < numtypes; i++)
  338.     doc->type[i] = types[i];
  339.       doc->type[numtypes] = NULL;
  340.       return(true);
  341.     }
  342.     if(FALSE == check_result){
  343.       return(false);
  344.     } 
  345.     if(0 == strcmp(temp_string, ":number-of-lines")) {
  346.       ReadLong(file,&lines);
  347.       doc->numLines = lines;
  348.     }
  349.     else if ((0 == strcmp(temp_string, ":number-of-bytes")) ||
  350.          (0 == strcmp(temp_string, ":number-of-characters"))){
  351.       ReadLong(file,&chars);
  352.       doc->numChars = chars;
  353.     }
  354.     else if(0 == strcmp(temp_string, ":best-line")){
  355.       ReadLong(file,&best);
  356.       doc->best = best;
  357.     }
  358.     else if(0 == strcmp(temp_string, ":date")){
  359.       if(FALSE == ReadString(dateStr, file, MAX_SYMBOL_SIZE)){
  360.     return(false);
  361.       }
  362.       else doc->date = s_strdup(dateStr);
  363.     }
  364.     else if(0 == strcmp(temp_string, ":headline")){
  365.       if(FALSE == ReadString(headline, file, MAX_SYMBOL_SIZE))
  366.     return(false);
  367.       doc->headline = s_strdup(headline);
  368.     }
  369.     else if(0 == strcmp(temp_string, ":doc-id")){
  370.       docid = (DocID*)s_malloc(sizeof(DocID));
  371.       if(FALSE == ReadDocID(docid, file)){
  372.     return(false);
  373.       }
  374.       doc->id = docid;
  375.     }
  376.     else if(0 == strcmp(temp_string, ":source")){
  377.       long return_value;
  378.       aSid = (SourceID)s_malloc(sizeof(_SourceID));
  379.       return_value = ReadSourceID(file, aSid);
  380.       if (return_value == END_OF_STRUCT_OR_LIST || return_value == false)
  381.     { s_free(aSid);
  382.       return(false);
  383.     }
  384.       doc->sourceID = aSid;
  385.     }
  386.     else if(strcmp(temp_string, ":type") == 0) {
  387.       if(FALSE == ReadString(temp_string, file, MAX_SYMBOL_SIZE))
  388.     return(false);
  389.       types[numtypes++] = s_strdup(temp_string);
  390.     }
  391.     else            /* we don't know what this is */
  392.       SkipObject(file);
  393.   }
  394.   doc->type = (char**)s_malloc((numtypes+1)*sizeof(char*));
  395.   for(i = 0; i < numtypes; i++)
  396.     doc->type[i] = types[i];
  397.  
  398.   doc->type[numtypes] = NULL;
  399.  
  400.   return(true);
  401. }
  402.  
  403. short ReadDocument(doc, file)
  404. DocumentID doc;
  405. FILE *file;
  406. {
  407.   CRetDocument document = NULL;
  408.   short status;
  409.   char temp_string[MAX_SYMBOL_SIZE];
  410.   short result = CheckStartOfStruct("document-id",file);
  411.   
  412. /*
  413.   start = end = NULL;
  414. */
  415.   doc->rawScore = doc->normalScore = -1;
  416.   
  417.   if (result == false)
  418.     return(false);
  419.   if (result == END_OF_STRUCT_OR_LIST)
  420.     return(END_OF_STRUCT_OR_LIST);
  421.     
  422.   while (TRUE)
  423.    { short check_result;
  424.      long val;
  425.      check_result = ReadSymbol(temp_string,file,MAX_SYMBOL_SIZE);
  426.  
  427.      if (check_result == false)
  428.        return(false);
  429.      if (check_result == END_OF_STRUCT_OR_LIST)
  430.        return(true);
  431.        
  432.      if (strcmp(temp_string,":score") == 0)
  433.       { if (ReadLong(file,&val) == false)
  434.           return(false);
  435.         doc->rawScore = (short)val;
  436.       }
  437.      else if (strcmp(temp_string,":document") == 0) {
  438.        document = MakeNewDocument();
  439.        status = ReadDoc(file, document);
  440.        if(status == false) {
  441.      fprintf(stderr, "error reading document structure.\n");
  442.        }
  443.        doc->doc = document;
  444.      }
  445.      else if(0 == strcmp(temp_string, ":start")){
  446.        if(FALSE == ReadFragment(file, &val))
  447.      return(false);
  448.        doc->start = val;
  449.      }
  450.      else if(0 == strcmp(temp_string, ":end")){
  451.        if(FALSE == ReadFragment(file, &val))
  452.      return(false);
  453.        doc->end = val;
  454.      }
  455.      else
  456.        SkipObject(file);
  457.    }
  458. }
  459.  
  460. CRetDocument
  461. MakeNewDocument()
  462. {
  463.   CRetDocument result;
  464.  
  465.   result = (CRetDocument)s_malloc(sizeof(_CRetDocument));
  466.   result->id = NULL;
  467.   result->sourceID = NULL;
  468.   result->myConnection= NULL;
  469.   result->numLines = 0;
  470.   result->numChars = 0;
  471.   result->blocks = result->pendingBlocks = NULL;
  472.   result->best = 0;
  473.   result->source = result->headline = result->city = NULL;
  474.   result->stock = result->company = result->industry = NULL;
  475.   result->type = NULL;
  476.   result->date = NULL;
  477.   result->next = result->prev = NULL;
  478.   result->paraStarts = NULL; /* should be array[1] = -1; */
  479.   
  480.   return(result);
  481. }
  482.  
  483.  
  484. DocList
  485. makeDocList(doc, rest)
  486. DocumentID doc;
  487. DocList rest;
  488. {
  489.   DocList result;
  490.   if((result = (DocList)s_malloc(sizeof(_DocList))) != NULL) {
  491.     result->thisDoc = doc;
  492.     result->nextDoc = rest;
  493.   }
  494.   return(result);
  495. }
  496.  
  497. static CRetDocument
  498. copy_cretdoc(doc)
  499. CRetDocument doc;
  500. {
  501.   CRetDocument result = NULL;
  502.   if(doc != NULL &&
  503.      (result = (CRetDocument)s_malloc(sizeof(_CRetDocument))) != NULL) {
  504.     result->id = copyDocID(doc->id);
  505.     result->sourceID = doc->sourceID; /* not copied - not freed! */
  506.     result->numLines = doc->numLines;
  507.     result->numChars = doc->numChars;
  508.     result->best = doc->best;
  509.     result->source = s_strdup(doc->source);
  510.     result->headline = s_strdup(doc->headline);
  511.     result->city = s_strdup(doc->city);
  512.     result->stock = s_strdup(doc->stock);
  513.     result->company = s_strdup(doc->company);
  514.     result->industry = s_strdup(doc->industry);
  515.     result->date = s_strdup(doc->date);
  516.     result->type = (char**)copyList(doc->type);
  517.   }
  518.   return result;
  519. }
  520.  
  521. DocumentID
  522. copy_docid(doc)
  523. DocumentID doc;
  524. {
  525.   DocumentID result;
  526.   
  527.   result = (DocumentID)s_malloc(sizeof(_DocumentID));
  528.   result->rawScore = doc->rawScore;
  529.   result->start = doc->start;
  530.   result->end = doc->end;
  531.   result->doc = copy_cretdoc(doc->doc);
  532.  
  533.   return result;
  534. }
  535.  
  536. void WriteDocument(doc, fp)
  537. DocumentID doc;
  538. FILE *fp;
  539. {
  540.   WriteStartOfStruct("document-id", fp);
  541.   WriteNewline(fp);
  542.   WriteSymbol(":score", fp);
  543.   WriteLong(doc->rawScore, fp);
  544.   WriteNewline(fp);
  545.   if(doc->start >= 0) {
  546.     WriteSymbol(":start", fp);
  547.     WriteNewline(fp);
  548.     WriteStartOfStruct("fragment", fp);
  549.     WriteNewline(fp);
  550.     WriteSymbol(":line-pos", fp);
  551.     WriteLong(doc->start, fp);
  552.     WriteEndOfStruct(fp);
  553.     WriteNewline(fp);
  554.   }
  555.   if(doc->end > 0) {
  556.     WriteSymbol(":end", fp);
  557.     WriteNewline(fp);
  558.     WriteStartOfStruct("fragment", fp);
  559.     WriteNewline(fp);
  560.     WriteSymbol(":line-pos", fp);
  561.     WriteLong(doc->end, fp);
  562.     WriteEndOfStruct(fp);
  563.     WriteNewline(fp);
  564.   }
  565.   if(doc->doc != NULL) {
  566.     WriteSymbol(":document", fp);
  567.     WriteNewline(fp);
  568.     WriteStartOfStruct("document", fp);
  569.     WriteNewline(fp);
  570.     if(doc->doc->headline != NULL) {
  571.       WriteSymbol(":headline", fp);
  572.       WriteString(doc->doc->headline, fp);
  573.     }
  574.     if (doc->doc->id != NULL) {
  575.       WriteNewline(fp);
  576.       WriteSymbol(":doc-id", fp);
  577.       WriteDocID(doc->doc->id, fp);
  578.       WriteNewline(fp);
  579.     }
  580.     if (doc->doc->sourceID != NULL) {
  581.       WriteSymbol(":source", fp);
  582.       WriteNewline(fp);
  583.       WriteStartOfStruct("source-id", fp);
  584.       WriteNewline(fp);
  585.       WriteSymbol(":filename", fp);
  586.       WriteString(doc->doc->sourceID->filename, fp);
  587.       WriteNewline(fp);
  588.       WriteEndOfStruct(fp);
  589.       WriteNewline(fp);
  590.     }
  591.     WriteSymbol(":number-of-lines", fp);
  592.     WriteLong(doc->doc->numLines, fp);
  593.     WriteNewline(fp);
  594.     WriteSymbol(":number-of-bytes", fp);
  595.     WriteLong(doc->doc->numChars, fp);
  596.     WriteNewline(fp);
  597.     if(doc->doc->type != NULL) {
  598.       char **doctypes;
  599.       for(doctypes = doc->doc->type;
  600.       *doctypes != NULL;
  601.       doctypes++) {
  602.     WriteSymbol(":type", fp);
  603.     WriteString(*doctypes, fp);
  604.     WriteNewline(fp);
  605.       }
  606.     }
  607.     WriteSymbol(":best-line", fp);
  608.     WriteLong(doc->doc->best, fp);
  609.     WriteNewline(fp);
  610.     if(doc->doc->date != NULL) {
  611.       WriteSymbol(":date", fp);
  612.       WriteString(doc->doc->date, fp);
  613.       WriteNewline(fp);
  614.     }
  615.     else {
  616.       WriteSymbol(":date", fp);
  617.       WriteString("0", fp);
  618.       WriteNewline(fp);
  619.     }
  620.     WriteNewline(fp);
  621.     WriteEndOfStruct(fp);
  622.   }
  623.   WriteNewline(fp);
  624.   WriteEndOfStruct(fp);
  625.   WriteNewline(fp);
  626. }
  627.  
  628. void sort_document_list(dlist)
  629. DocList dlist;
  630. {
  631.   DocList d;
  632.   DocumentID di;
  633.   Boolean Changed = TRUE;
  634.  
  635.   while(Changed) {
  636.     Changed = FALSE;
  637.     for(d = dlist; d != NULL && d->nextDoc != NULL; d = d->nextDoc)
  638.       if(d->thisDoc != NULL && d->nextDoc->thisDoc != NULL)
  639.     if(d->thisDoc->rawScore < d->nextDoc->thisDoc->rawScore) {
  640.       Changed = TRUE;
  641.       di = d->thisDoc;
  642.       d->thisDoc = d->nextDoc->thisDoc;
  643.       d->nextDoc->thisDoc = di;
  644.     }
  645.   }
  646. }
  647.       
  648. DocList
  649. findLast(dlist)
  650. DocList dlist;
  651. {
  652.   DocList d;
  653.  
  654.   if(dlist == NULL || dlist->nextDoc == NULL) return dlist;
  655.   for(d = dlist; d->nextDoc != NULL; d = d->nextDoc);
  656.   return d;
  657. }
  658.  
  659. DocumentID
  660. findDoc(dlist, number)
  661. DocList dlist;
  662. int number;
  663. {
  664.   DocList d;
  665.   int i;
  666.  
  667.   for(i = 0, d = dlist; (d != NULL) && (i < number); i++, d = d->nextDoc);
  668.  
  669.   if (d != NULL)
  670.     return(d->thisDoc);
  671.   else
  672.     return(NULL);
  673. }
  674.  
  675. DocumentID
  676. fillDocumentID(docHeader, source)
  677. WAISDocumentHeader* docHeader;
  678. SourceID source;
  679. {
  680.   DocumentID docID;
  681.  
  682.   if((docID = (DocumentID)s_malloc(sizeof(_DocumentID))) != NULL) {
  683.     docID->rawScore = docHeader->Score;
  684.     docID->start = docID->end = -1;
  685.     if((docID->doc = (CRetDocument)s_malloc(sizeof(_CRetDocument))) != NULL) {
  686.       docID->doc->sourceID = source;
  687.       /*      docID->doc->version = docHeader->VersionNumber; */
  688.       docID->doc->numLines = docHeader->Lines;
  689.       docID->doc->numChars = docHeader->DocumentLength;
  690.       docID->doc->best = docHeader->BestMatch;
  691.  
  692.       if(docHeader->Headline != NULL) {
  693.     docID->doc->headline = s_strdup(docHeader->Headline);
  694.     /*strip_lf(docID->doc->headline);*/
  695.       }
  696.       if(docHeader->Source != NULL)
  697.     docID->doc->source = s_strdup(docHeader->Source);
  698.       if(docHeader->OriginCity != NULL)
  699.     docID->doc->city = s_strdup(docHeader->OriginCity);
  700.       if(docHeader->Date != NULL)
  701.     docID->doc->date = s_strdup(docHeader->Date);
  702.       if(docHeader->Types != NULL) {
  703.     char **types = docHeader->Types;
  704.     long numtypes = 0, t;
  705.     while (*types++) numtypes++;
  706.     docID->doc->type = (char **)s_malloc((numtypes+1)*sizeof(char*));
  707.     for(types = docHeader->Types, t=0;
  708.         t < numtypes;
  709.         t++)
  710.       docID->doc->type[t] = s_strdup(types[t]);
  711.     docID->doc->type[numtypes] = NULL;
  712.       }
  713.       else {
  714.     docID->doc->type = (char **)s_malloc(2*sizeof(char*));
  715.     docID->doc->type[0] = s_strdup("TEXT");
  716.     docID->doc->type[1] = NULL;
  717.       }
  718.       if((docID->doc->id = docIDFromAny(docHeader->DocumentID))
  719.     == NULL) {
  720.     docID->doc->id = (DocID*)s_malloc(sizeof(DocID));
  721.     memset(docID->doc->id, 0, sizeof(DocID));
  722.     docID->doc->id->originalLocalID =
  723.       duplicateAny(docHeader->DocumentID);
  724.       }
  725. /*
  726.       if(docHeader->DocumentID != NULL)
  727.     docID->doc->id->originalLocalID =
  728.       duplicateAny(docHeader->DocumentID);
  729. */
  730.     }
  731.   }
  732.   return docID;
  733. }
  734.  
  735. void
  736. freeCRetDocument(doc)
  737. CRetDocument doc;
  738. {
  739.   s_free(doc->source);
  740.   s_free(doc->headline);
  741.   s_free(doc->city);
  742.   s_free(doc->stock);
  743.   s_free(doc->company);
  744.   s_free(doc->industry);
  745.   s_free(doc->date);
  746.   if(doc->type != NULL)
  747.     freeList(doc->type);
  748.   freeDocID(doc->id);
  749.   s_free(doc);
  750. }
  751.  
  752. void
  753. freeDocumentID(docID)
  754. DocumentID docID;
  755. {
  756.   if(docID != NULL) {
  757.     if(docID->doc != NULL) {
  758.       freeCRetDocument(docID->doc);
  759.       docID->doc = NULL;
  760.     }
  761.     s_free(docID);
  762.   }
  763. }
  764.  
  765. void
  766. freeDocList(doclist)
  767. DocList doclist;
  768. {
  769.   DocList dl;
  770.   while(doclist != NULL) {
  771.     freeDocumentID(doclist->thisDoc);
  772.     dl = doclist;
  773.     doclist = doclist->nextDoc;
  774.     s_free(dl);
  775.   }
  776. }
  777.